import { join } from 'path'

import fg from 'fast-glob'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import { omit } from 'lodash'
import { Configuration, DefinePlugin } from 'webpack'
import { merge } from 'webpack-merge'

import { IgnoreNotFoundExportPlugin } from './ignore-not-found-plugin'

const { getReplaceConfig } = require('@slardar/rollup')

const { rootDir, packageDir } = require('./consts')
const webpackBaseConfig = require('./webpack.cypress')

const cypressDir = join(rootDir, 'cypress')
const distDir = join(rootDir, 'dist')
const webpackConfig = createBaseWebpackConfig()

export type PagePath = keyof typeof pageCompilerConfigs

export const pageCompilerConfigs = {
  'sdk-npm.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'sdk-npm', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'sdk-npm-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-npm', 'index.html'),
        filename: 'sdk-npm.html',
      }),
    ],
  }),
  'sdk-inline.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'sdk-script', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'sdk-script-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-script', 'index.html'),
        filename: 'sdk-inline.html',
      }),
    ],
  }),
  'sdk-script-base.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'sdk-script', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'sdk-script-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-script', 'base.html'),
        filename: 'sdk-script-base.html',
      }),
    ],
  }),
  'web.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'index.tsx'),

    output: {
      path: distDir,
      filename: 'web-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'index.html'),
        filename: 'web.html',
      }),
    ],
  }),
  'web-precollect.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'index.tsx'),

    output: {
      path: distDir,
      filename: 'web-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'precollect.html'),
        filename: 'web-precollect.html',
      }),
    ],
  }),
  'web-npm.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'npm.tsx'),

    output: {
      path: distDir,
      filename: 'web-npm.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'npm.html'),
        filename: 'web-npm.html',
      }),
    ],
  }),
  'web-minimal.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'minimal.tsx'),

    output: {
      path: distDir,
      filename: 'web-minimal.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'npm.html'),
        filename: 'web-minimal.html',
      }),
    ],
  }),
  'web-multi-instances.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'multi-instances.tsx'),

    output: {
      path: distDir,
      filename: 'web-multi-instances.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'index.html'),
        filename: 'web-multi-instances.html',
      }),
    ],
  }),
  'web-multi-precollect.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'multi-instances.tsx'),

    output: {
      path: distDir,
      filename: 'web-multi-instances.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'precollect.html'),
        filename: 'web-multi-precollect.html',
      }),
    ],
  }),
  'web-multiBidSender.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'web', 'src', 'multiBidSender.tsx'),

    output: {
      path: distDir,
      filename: 'web-multiBidSender.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'web', 'npm.html'),
        filename: 'web-multiBidSender.html',
      }),
    ],
  }),
  'apmplus-web.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'apmplus-web', 'src', 'index.tsx'),

    output: {
      path: distDir,
      filename: 'apmplus-web-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'apmplus-web', 'index.html'),
        filename: 'apmplus-web.html',
      }),
    ],
  }),
  'apmplus-web-precollect.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'apmplus-web', 'src', 'index.tsx'),

    output: {
      path: distDir,
      filename: 'apmplus-web-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'apmplus-web', 'precollect.html'),
        filename: 'apmplus-web-precollect.html',
      }),
    ],
  }),
  'apmplus-web-npm.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'apmplus-web', 'src', 'npm.tsx'),

    output: {
      path: distDir,
      filename: 'apmplus-web-npm.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'apmplus-web', 'npm.html'),
        filename: 'apmplus-web-npm.html',
      }),
    ],
  }),
  'apmplus-web-multi-instances.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'apmplus-web', 'src', 'multi-instances.tsx'),

    output: {
      path: distDir,
      filename: 'apmplus-web-multi-instances.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'apmplus-web', 'index.html'),
        filename: 'apmplus-web-multi-instances.html',
      }),
    ],
  }),
  'apmplus-web-multi-precollect.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'apmplus-web', 'src', 'multi-instances.tsx'),

    output: {
      path: distDir,
      filename: 'apmplus-web-multi-instances.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'apmplus-web', 'precollect.html'),
        filename: 'apmplus-web-multi-precollect.html',
      }),
    ],
  }),
  'base.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'base', 'src', 'index.tsx'),
    output: {
      path: distDir,
      filename: 'base-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'base', 'npm.html'),
        filename: 'base.html',
      }),
    ],
  }),
  'sdk-hybrid.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'sdk-hybrid', 'src', 'index.tsx'),
    },
    output: {
      path: distDir,
      filename: 'sdk-hybrid-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-hybrid', 'index.html'),
        filename: 'sdk-hybrid.html',
      }),
    ],
  }),
  'slardar-lite.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'slardar-lite', 'src', 'index.tsx'),

    output: {
      path: distDir,
      filename: 'slardar-lite-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'slardar-lite', 'index.html'),
        filename: 'slardar-lite.html',
      }),
    ],
  }),
  'sdk-script-sri.html': merge(webpackConfig, {
    entry: join(cypressDir, 'projects', 'sdk-script-sri', 'src', 'index.tsx'),

    output: {
      path: distDir,
      filename: 'sdk-script-sri-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-script-sri', 'index.html'),
        filename: 'sdk-script-sri.html',
      }),
    ],
  }),
  'rum-test.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'rum-test', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'rum-test-main.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'rum-test', 'index.html'),
        filename: 'rum-test.html',
      }),
    ],
  }),
  'sdk-init-config-script.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'sdk-init-config-script', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'sdk-init-config-script.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-init-config-script', 'index.html'),
        filename: 'sdk-init-config-script.html',
      }),
    ],
  }),
  'rangers-site-sdk.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'rangers-site-sdk', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'rangers-site-sdk.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'rangers-site-sdk', 'index.html'),
        filename: 'rangers-site-sdk.html',
      }),
    ],
  }),
  'rangers-site-sdk-precollect.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'rangers-site-sdk', 'src', 'empty.ts'),
    },

    output: {
      path: distDir,
      filename: 'rangers-site-sdk.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'rangers-site-sdk', 'precollect.html'),
        filename: 'rangers-site-sdk-precollect.html',
      }),
    ],
  }),
  'sdk-multi-instance.html': merge(webpackConfig, {
    entry: {
      app: join(cypressDir, 'projects', 'sdk-multi-instance', 'src', 'index.tsx'),
    },

    output: {
      path: distDir,
      filename: 'sdk-multi-instance.[contenthash].js',
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: join(cypressDir, 'projects', 'sdk-multi-instance', 'index.html'),
        filename: 'sdk-multi-instance.html',
      }),
    ],
  }),
}

const SlardarPlugins = [
  { name: 'worker', target: 'webworker' },
  { name: 'monitors', target: 'web' },
  { name: 'sentry', target: 'web' },
  { name: 'heatmap-draw', target: 'web' },
  { name: 'heatmap-mouse-draw', target: 'web' },
  { name: 'heatmap-scroll-draw', target: 'web' },
  { name: 'heatmap', target: 'web' },
]

const SdkPlugins = fg
  .sync(join(packageDir, 'web', 'src', 'plugin-entries', '*.ts'), { objectMode: true })
  .map(({ name }) => ({
    name: name.split('.')[0],
    target: 'web',
  }))

export type SdkDependKey = keyof typeof sdkCompilerConfigs

const istanbulBabelLoader = {
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env', '@babel/preset-typescript'],
              plugins: ['istanbul'],
            },
          },
        ],
      },
    ],
  },
}

export const sdkCompilerConfigs = {
  'browser.cn.js': merge(webpackConfig, {
    entry: join(packageDir, 'browser', 'src', 'script.ts'),
    mode: 'production',
    output: {
      path: join(distDir, 'cn'),
      filename: 'browser.cn.js',
      library: 'Slardar',
      libraryExport: 'default',
      libraryTarget: 'window',
    },
    optimization: {
      minimize: false,
      splitChunks: false,
    },
  }),
  'browser-sdk-plugins': SlardarPlugins.map(({ name, target }) =>
    merge(webpackConfig, {
      entry: join(packageDir, 'browser', 'src', 'plugins', `${name}.ts`),
      mode: 'production',
      target: target,
      output: {
        path: join(distDir, 'cn', 'plugins'),
        filename: `${name}.cn.js`,
      },
      optimization: {
        minimize: false,
        splitChunks: false,
      },
    }),
  ),
  'rangers-site-sdk': merge(omit(webpackConfig, 'plugins'), {
    entry: join(packageDir, 'rangers-site-sdk', 'src', 'index.ts'),
    mode: 'production',
    output: {
      path: join(distDir, 'cn'),
      filename: 'rangers-site-sdk.cn.js',
    },
    plugins: [
      new DefinePlugin(
        getReplaceConfig({
          packageJson: {
            version: '0.0.0',
          },
          region: 'rangers-cn',
          clientMode: 'browser',
          sdkName: 'RangersSiteSDK',
        }),
      ),
    ],
    optimization: {
      minimize: false,
      splitChunks: false,
    },
  }),
  'web-browser.js': merge(webpackConfig, {
    entry: join(packageDir, 'web', 'src', 'script.ts'),
    mode: 'production',
    output: {
      path: join(distDir, 'cn'),
      filename: 'web-browser.js',
    },
    optimization: {
      minimize: false,
      splitChunks: false,
    },
    ...istanbulBabelLoader,
  }),
  'web-plugin-entries': SdkPlugins.map(({ name, target }) =>
    merge(webpackConfig, {
      entry: join(packageDir, 'web', 'src', 'plugin-entries', `${name}.ts`),
      mode: 'production',
      target: target,
      output: {
        path: join(distDir, 'cn', 'plugins'),
        filename: `${name}.0.0.0.debug.js`,
      },
      optimization: {
        minimize: false,
        splitChunks: false,
      },
      ...istanbulBabelLoader,
    }),
  ),
  'apmplus-web.js': merge(webpackConfig, {
    entry: join(packageDir, 'apmplus-web', 'src', 'script.ts'),
    mode: 'production',
    output: {
      path: join(distDir, 'cn'),
      filename: 'apmplus-web.js',
    },
    optimization: {
      minimize: false,
      splitChunks: false,
    },
    ...istanbulBabelLoader,
  }),
}

//TODO: 整理页面和 slardar sdk 脚本依赖关系，这里先全量依赖
export const pageDepends: Record<PagePath, SdkDependKey[]> = {
  'sdk-npm.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'sdk-inline.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'sdk-script-base.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web-precollect.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web-npm.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web-minimal.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web-multi-instances.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web-multi-precollect.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'web-multiBidSender.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'apmplus-web.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'apmplus-web-precollect.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'apmplus-web-npm.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'apmplus-web-multi-instances.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'apmplus-web-multi-precollect.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'base.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'sdk-hybrid.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'slardar-lite.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'sdk-script-sri.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'rum-test.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'sdk-init-config-script.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'rangers-site-sdk.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'rangers-site-sdk-precollect.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
  'sdk-multi-instance.html': Object.keys(sdkCompilerConfigs) as SdkDependKey[],
}

function createBaseWebpackConfig(): Configuration {
  return merge(webpackBaseConfig, {
    mode: 'development',

    // debug 时找不到 sourcemap 对应文件，源码没有混淆，直接 debug 源码即可
    // devtool: 'cheap-module-source-map',

    output: {
      path: distDir,
    },

    resolve: {
      alias: {
        '@slardar/sdk-core': join(packageDir, 'core', 'src', 'index.ts'),
        '@slardar/sdk': join(packageDir, 'browser', 'src'),
        '@slardar/sdk-template': join(packageDir, 'sdk-template', 'src', 'index.ts'),
        '@slardar/web': join(packageDir, 'web', 'src', 'index.ts'),
        '@slardar/helper': join(packageDir, 'helper', 'src', 'index.ts'),
        '@slardar/base': join(packageDir, 'base', 'src', 'index.ts'),
        '@apmplus/web': join(packageDir, 'apmplus-web', 'src', 'index.ts'),
        '@apmplus/integrations': join(packageDir, 'apmplus-integrations', 'src', 'index.ts'),
        '@slardar/integrations': join(packageDir, 'integrations', 'src', 'index.ts'),
        '@slardar/sdk-web': join(packageDir, 'sdk-web', 'src', 'index.ts'),
        '@slardar/polyfill': join(packageDir, 'polyfill'),
        '@slardar/hybrid': join(packageDir, 'hybrid', 'src', 'script.ts'),
        '@slardar/react': join(packageDir, 'slardar-react', 'src'),
        '@slardar/types': join(packageDir, 'types', 'src'),
        '@slardar/trace': join(packageDir, 'trace', 'src'),
        '@apm-insight-web/rangers-site-sdk': join(packageDir, 'rangers-site-sdk', 'src', 'index.ts'),
        '@slardar/sdk-lite': join(packageDir, 'slardar-lite', 'src', 'index.ts'),
        '@slardar/sdk-lite/middlewares': join(packageDir, 'slardar-lite', 'src', 'middlewares', 'index.ts'),
        '@slardar/sdk-lite/collector': join(packageDir, 'slardar-lite', 'src', 'collector', 'index.ts'),
      },
    },

    optimization: {
      splitChunks: {
        chunks: 'initial',
        minSize: 0,
        minChunks: 1,
        maxInitialRequests: Infinity,
        maxAsyncRequests: Infinity,
        cacheGroups: {
          'vendor-async': {
            name: 'vendor-async',
            test: /[\\/]node_modules[\\/]/,
            priority: 110,
            chunks: 'async',
          },
          'async-component': {
            name: 'async-component',
            test: /[\\/]src[\\/]/,
            priority: 110,
            chunks: 'async',
          },
          antd: {
            name: 'antd',
            test: /[\\/]node_modules[\\/](antd|@ant-design|rc-[^\\/]+)[\\/]/,
            priority: 100,
          },
          react: {
            name: 'react',
            test: /[\\/]node_modules[\\/](react|react-dom|scheduler)[\\/]/,
            priority: 100,
          },
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendor',
            priority: 90,
          },
        },
      },
    },

    plugins: [
      new IgnoreNotFoundExportPlugin(),
      new DefinePlugin(
        omit(
          getReplaceConfig({
            packageJson: {
              version: '0.0.0',
            },
            region: 'cn',
          }),
          'process.env.NODE_ENV',
        ),
      ),
    ],
  })
}
